﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace Solution.MouseMover.WinFormsApp
{

  /// <summary>
  /// The main application window.
  /// </summary>
  public partial class ApplicationForm : Form
  {

    private MouseMoverEngine _mouseMoverEngine;

    /// <summary>
    /// The system tray icon uses four frames of animation:
    ///   1:CENTRE 2:LEFT 3:CENTRE 4:RIGHT
    /// </summary>
    private int _frameCounter = 1;

    /// <summary>
    /// Determines whether the animiation is enabled. Note that the event handler
    /// to turn on or off the animation needs to manually reset the animiation to
    /// the first frame (see _frameCounter).
    /// </summary>
    private bool _animationEnabled = true;

    /// <summary>
    /// A flag indicating if the application should _really_ exit. Used to allow
    /// for the minimize to system tray functionality.
    /// </summary>
    private bool _applicationExit = false;

    /// <summary>
    /// The same EventHandler is used by the system tray right-click menu and the 
    /// checkbox. Using a single EventHandler makes the logic to check or uncheck
    /// both of the checkbox indicators simpler.
    /// </summary>
    private EventHandler _mouseMoveEventHandler;

    /// <summary>
    /// The same EventHandler is used by the system tray right-click menu and the 
    /// checkbox. Using a single EventHandler makes the logic to check or uncheck
    /// both of the checkbox indicators simpler.
    /// </summary>
    private EventHandler _animationEventHandler;


    public ApplicationForm()
    {
      InitializeComponent();
      this._mouseMoverEngine = new MouseMoverEngine();
      this._animationEventHandler = new System.EventHandler(this.AnimationEventHandler);
      this._mouseMoveEventHandler = new System.EventHandler(this.MouseMoveEventHandler);
      this.cbxAnimate.CheckedChanged += this._animationEventHandler;
      this.mnuTrayAnimate.Click += this._animationEventHandler;
      this.cbxMouseMove.CheckedChanged += this._mouseMoveEventHandler;
      this.mnuTrayMouseMove.Click += this._mouseMoveEventHandler;
    }

    #region Event Handlers

    private void mnuFileMinimize_Click(object sender, EventArgs e)
    {
      this.Close();
    }

    private void mnuTrayShow_Click(object sender, EventArgs e)
    {
      this.ShowAndActivate();
    }

    private void mnuHelpAbout_Click(object sender, EventArgs e)
    {
      MessageBox.Show(Application.ProductName + " Version " + Application.ProductVersion);
    }

    private void mnuExit_Click(object sender, EventArgs e)
    {
      this.ApplicationExit();
    }

    /// <summary>
    /// Shows or hides the application window when the system tray icon is double-clicked.
    /// </summary>
    private void systemTrayIcon_MouseDoubleClick(object sender, MouseEventArgs e)
    {
      if (e.Button == System.Windows.Forms.MouseButtons.Left)
      {
        //this.Visible = !this.Visible;
        if (this.Visible)
        {
          this.Visible = false;
        }
        else
        {
          this.ShowAndActivate();
        }
      }
    }

    private void ShowAndActivate()
    {
      this.Visible = true;
      this.BringToFront();
      this.Activate();
    }

    /// <summary>
    /// Handles the FormClosing() event to hide ("minimize") the application to the system tray.
    /// </summary>
    private void ApplicationForm_FormClosing(object sender, FormClosingEventArgs e)
    {
      if (!this._applicationExit)
      {
        this.Visible = false;
        e.Cancel = true;
        this.ShowBalloonTip();
      }
    }

    #endregion

    private void ShowBalloonTip()
    {
      // TODO: Move this text to the Resources file.
      this.systemTrayIcon.ShowBalloonTip(5000,"MouseMover","MouseMover is still running. Double-click the icon to show or hide MouseMover. Right-click the icon for additional options.",ToolTipIcon.Info);
    }

    /// <summary>
    /// Exits the application.
    /// </summary>
    private void ApplicationExit()
    {
      this._applicationExit = true;
      Application.Exit();
    }

    #region Shared Checkbox/MenuItem Event Handlers

    /// <summary>
    /// The same EventHandler is used by the system tray right-click menu and the 
    /// checkbox. Using a single EventHandler makes the logic to check or uncheck
    /// both of the checkbox indicators simpler.
    /// </summary>
    private void AnimationEventHandler(object sender, EventArgs e)
    {
      this.cbxAnimate.CheckedChanged -= this._animationEventHandler;
      this.mnuTrayAnimate.Click -= this._animationEventHandler;

      this._animationEnabled = !this._animationEnabled;
      this.cbxAnimate.Checked = this._animationEnabled;
      this.mnuTrayAnimate.Checked = this._animationEnabled;

      this.cbxAnimate.CheckedChanged += this._animationEventHandler;
      this.mnuTrayAnimate.Click += this._animationEventHandler;
    }

    /// <summary>
    /// The same EventHandler is used by the system tray right-click menu and the 
    /// checkbox. Using a single EventHandler makes the logic to check or uncheck
    /// both of the checkbox indicators simpler.
    /// </summary>
    private void MouseMoveEventHandler(object sender, EventArgs e)
    {
      this.mnuTrayMouseMove.Click -= this._mouseMoveEventHandler;
      this.cbxMouseMove.CheckedChanged -= this._mouseMoveEventHandler;

      this.tmrMouseMove.Enabled = !this.tmrMouseMove.Enabled;
      this.tmrMouseIcon.Enabled = !this.tmrMouseIcon.Enabled;
      this.cbxMouseMove.Checked = this.tmrMouseMove.Enabled;
      this.mnuTrayMouseMove.Checked = this.tmrMouseMove.Enabled;
      this._frameCounter = 1;
      this.systemTrayIcon.Icon = Properties.Resources.MouseIcon05_01;

      this.mnuTrayMouseMove.Click += this._mouseMoveEventHandler;
      this.cbxMouseMove.CheckedChanged += this._mouseMoveEventHandler;
    }

    #endregion

    #region Timer Event Handlers

    /// <summary>
    /// The Timer event that runs the MouseMoverEngine.
    /// </summary>
    private void tmrMouseMove_Tick(object sender, EventArgs e)
    {
      try
      {
        this._mouseMoverEngine.Move();
      }
      catch(Exception exception)
      {
        // TODO: Logging
        MessageBox.Show(exception.ToString());
      }
    }

    /// <summary>
    /// The Timer event that runs the system tray animation.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void tmrMouseIcon_Tick(object sender, EventArgs e)
    {
      #region ANIMATION
      if (this._animationEnabled)
      {
        switch (this._frameCounter)
        {
          case 1:
            this.systemTrayIcon.Icon = Properties.Resources.MouseIcon05_01;
            break;
          case 2:
            this.systemTrayIcon.Icon = Properties.Resources.MouseIcon05_02;
            break;
          case 3:
            this.systemTrayIcon.Icon = Properties.Resources.MouseIcon05_01;
            break;
          case 4:
            this.systemTrayIcon.Icon = Properties.Resources.MouseIcon05_03;
            break;
        }
        if (this._frameCounter < 4)
        {
          this._frameCounter++;
        }
        else
        {
          this._frameCounter = 1;
        }
      }
      else
      {
        // Set icon in case someone switches the property in the middle of an animation 
        // sequence. There are more efficient ways to do this but this is a simple way.
        this.systemTrayIcon.Icon = Properties.Resources.MouseIcon05_01;
      }
      #endregion ANIMATION
    }

    #endregion

  }

}